package controller

import (
	"fmt"
	"time"

	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/project/breeder/breeder/cooperated"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/def"
	"gddgame.cc/galaxy/utils/orm"
)

func GetUnit(context def.Context, userUnitId string) (*model.UserUnit, error) {
	var userUnit model.UserUnit

	err := Env.Cache("unit/"+utils.ToString(userUnitId), &userUnit, func() error {
		if ok, err := model.UserUnitModel.Query().Where("=", "id", userUnitId).One(&userUnit); !ok {
			return EmptyExceptionDetail("UNIT_NOEXIST", err)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return &userUnit, nil
}
func GetUnitWithUser(context def.Context, userUnitId string, user *model.User) (*model.UserUnit, error) {
	var userUnit model.UserUnit

	err := Env.Cache("unit/"+utils.ToString(userUnitId), &userUnit, func() error {
		query := model.UserUnitModel.Query().Where("=", "id", userUnitId)
		if user != nil {
			query.Where("=", "user_id", user.Id)
		}
		if ok, err := query.One(&userUnit); !ok {
			return EmptyExceptionDetail("UNIT_NOEXIST", err)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	userUnit.Schema = model.UserUnitModel.Schema()
	return &userUnit, nil
}

func SaveUnit(context def.Context, userUnit *model.UserUnit) error {
	//fmt.Println("save", userUnit)
	if err := Env.SingleClean("unit/"+utils.ToString(userUnit.Id), func() error {
		//fmt.Println("clean", userUnit, userUnit.CreateTime == nil)
		if _, err := model.UserUnitModel.PK(userUnit.Id).Save(userUnit.CreateTime == nil, userUnit); err != nil {
			fmt.Println(err)
			return SystemExceptionDetail("更新部队失败", err)
		}
		return nil
	}, false); err != nil {
		return err
	}
	return nil
}
func UpdateUnit(context def.Context, userUnit *model.UserUnit, data map[string]interface{}) error {
	//fmt.Println("save", userUnit)
	if err := Env.SingleClean("unit/"+utils.ToString(userUnit.Id), func() error {
		//fmt.Println("clean", userUnit, userUnit.CreateTime == nil)
		if _, err := model.UserUnitModel.PK(userUnit.Id).Update(data); err != nil {
			fmt.Println(err)
			return SystemExceptionDetail("更新部队失败", err)
		}
		return nil
	}, false); err != nil {
		return err
	}
	return nil
}

func InsertUnit(context def.Context, userUnit *model.UserUnit, user *model.User) error {
	if _, err := model.UserUnitModel.PK(userUnit.Id).Save(true, userUnit); err != nil {
		return SystemExceptionDetail("添加部队失败", err)
	}
	return nil
}

func DeleteUnit(context def.Context, userUnitId string) error {
	if err := Env.Clean("user/" + utils.ToString(userUnitId)); err != nil {
		return err
	}
	if _, err := model.UserUnitModel.PK(userUnitId).Delete(); err != nil {
		return SystemExceptionDetail("删除部队失败", err)
	}
	return nil
}

func ChangeUnitTargetMode(context def.Context, targetMode int, user *model.User, userUnit *model.UserUnit) (err error) {
	if err := UpdateUnit(context, userUnit, map[string]interface{}{
		"target_mode": targetMode,
	}); err != nil {
		return SystemExceptionDetail("调整部队失败", err)
	}
	return
}
func ChangeUnitAiMode(context def.Context, aiMode int, user *model.User, userUnit *model.UserUnit) (err error) {
	if err := UpdateUnit(context, userUnit, map[string]interface{}{
		"ai_mode": aiMode,
	}); err != nil {
		return SystemExceptionDetail("调整部队失败", err)
	}
	return
}
func ChangeUnitGroup(context def.Context, group int, user *model.User, userUnit *model.UserUnit) (err error) {
	if userUnit.Group == group {
		return nil
	}

	if _, err = model.UserUnitModel.Query().Where("=", "group", group).Update(map[string]interface{}{
		"group": group,
	}); err != nil {
		return SystemExceptionDetail("查找用户部队失败", err)
	}

	if err := Env.SingleClean("unit/"+utils.ToString(userUnit.Id), func() error {
		if _, err := model.UserUnitModel.PK(userUnit.Id).Update(map[string]interface{}{
			"group": group,
		}); err != nil {
			return SystemExceptionDetail("部队编组失败", err)
		}
		return nil
	}, false); err != nil {
		return err
	}
	return nil
}
func ChangeUnitIndex(context def.Context, index int, user *model.User, userUnit *model.UserUnit) (err error) {
	if userUnit.Index < 0 {
		return
	}
	targetIndex := index
	if userUnit.Index < index {
		targetIndex = userUnit.Index
	}
	var userUnits []model.UserUnit
	if _, err = model.UserUnitModel.Query().Where("=", "user_id", user.Id).Where(">=", "index", targetIndex).Find(&userUnits); err != nil {
		return SystemExceptionDetail("查找用户部队失败", err)
	}

	if _, err = model.UserUnitModel.Query().Where(">", "index", userUnit.Index).Update(map[string]interface{}{
		"index": &orm.UpdateOperate{Operate: "-", Value: 1},
	}); err != nil {
		return SystemExceptionDetail("查找用户部队失败", err)
	}
	if index >= 0 {
		if _, err = model.UserUnitModel.Query().Where(">=", "index", index).Update(map[string]interface{}{
			"index": &orm.UpdateOperate{Operate: "+", Value: 1},
		}); err != nil {
			return SystemExceptionDetail("查找用户部队失败", err)
		}
	}

	keys := []string{}
	for _, unit := range userUnits {
		keys = append(keys, "unit/"+utils.ToString(unit.Id))
	}
	if err := Env.BatchClean(keys, func() error {
		return nil
	}, false); err != nil {
		return err
	}

	if err := Env.SingleClean("unit/"+utils.ToString(userUnit.Id), func() error {
		data := map[string]interface{}{
			"index": index,
		}
		// 下场
		if index == -1 {
			data["group"] = 0
		}
		if _, err := model.UserUnitModel.PK(userUnit.Id).Update(data); err != nil {
			return SystemExceptionDetail("部队下场错误", err)
		}
		return nil
	}, false); err != nil {
		return err
	}
	return nil
}
func UpgradeUnitPower(context def.Context, powerId int, user *model.User, account *cooperated.Account, userUnit *model.UserUnit, unit *cooperated.Unit) (err error) {
	powerInfo, ok := Center.PowerMap[powerId]
	if !ok {
		return ValidException("天赋数据错误")
	}
	if userUnit.Index >= 0 {
		return ValidException("部队作战中")
	}
	level, ok := userUnit.Powers[powerId]
	if ok {
		if level+1 == len(powerInfo.Levels) {
			return ValidException("天赋已经满级")
		}
		level += 1
	} else {
		level = 1
	}
	levelInfo := powerInfo.Levels[level-1]
	if !ValidRequire(context, levelInfo.RequireSlice, user, account, userUnit, unit) {
		return ValidException("不满足升级条件")
	}
	ok, consumeData := ValidConsume(context, levelInfo.ConsumeSlice, 1, user, userUnit)
	if !ok {
		return ValidException("升级所需不足")
	}
	if userUnit.Powers == nil {
		userUnit.Powers = map[int]int{}
	}
	userUnit.Powers[powerId] = level
	if consumeData.UserUnitData == nil {
		consumeData.UserUnitData = map[string]interface{}{}
	}
	consumeData.UserUnitData["powers"] = userUnit.Powers
	userUnitData := consumeData.UserUnitData

	consumeData.UserUnitData = nil
	if err := UpdateConsume(context, consumeData, user, userUnit); err != nil {
		return err
	}

	if err := UpdateUnit(context, userUnit, userUnitData); err != nil {
		return SystemExceptionDetail("调整部队失败", err)
	}
	return nil
}

func ResetUnitPower(context def.Context, user *model.User, userUnit *model.UserUnit) (err error) {
	if len(userUnit.Powers) == 0 {
		return
	}
	unit := Center.UnitMap[userUnit.UnitId]
	level := unit.Levels[userUnit.Level]
	userUnit.Powers = map[int]int{}
	userUnit.Power = level.PowerPoint

	if err := Env.SingleClean("unit/"+utils.ToString(userUnit.Id), func() error {
		if _, err := model.UserUnitModel.PK(userUnit.Id).Update(map[string]interface{}{
			"powers": map[int]int{},
			"power":  userUnit.Power,
		}); err != nil {
			return SystemExceptionDetail("调整部队失败", err)
		}
		return nil
	}, false); err != nil {
		return err
	}
	return
}

func ClearUnits(context def.Context) (int, error) {
	n, err := model.UserUnitModel.Query().Delete()
	if err != nil {
		return 0, err
	}
	_, _ = model.UserEquipModel.Query().Update(map[string]interface{}{
		"unit_id": 0,
	})
	return utils.ToInt(n), err
}

func GetUnits(context def.Context, userId int, updateTime *time.Time, unitMap map[string]*cooperated.Unit) (userUnits []*model.PlayerUnit, err error) {
	var uUnits []model.UserUnit
	query := model.UserUnitModel.Query().Where("=", "user_id", userId)
	if updateTime != nil && updateTime.After(Env.Time()) {
		query.Where(">", "update_time", updateTime)
	}
	if _, err = query.Find(&uUnits); err != nil {
		return nil, SystemExceptionDetail("查找用户部队失败", err)
	}
	// 获取道具信息
	userUnits = make([]*model.PlayerUnit, 0)
	for key := range uUnits {
		uT := uUnits[key]
		unit, ok := unitMap[uT.Id]
		if !ok {
			continue
		}
		userUnits = append(userUnits, model.NewPlayerUnit(&uT, unit.GetAttrWithId(Center.HealthId), unit.Status, unit))
	}
	return userUnits, nil
}

func GetUnitDetail(context def.Context, userUnit *model.UserUnit, unit *cooperated.Unit, statData map[string]int32) (*model.PlayerUnitDetail, error) {
	data := map[string]int{}
	for _, item := range Center.RelationMap[utils.ToString(model.UnitType)] {
		// 从数据中->属性中->
		value, ok := unit.PropInstance.GetProp2(item.Key)
		//fmt.Println(item.Key, value, ok)
		if !ok && userUnit != nil {
			var err error
			value, err = userUnit.Get(userUnit, item.Key)
			if err != nil {
				value = unit.AbilityProp.GetAttrWithKey(item.Key)
			} else {
				value = utils.ToInt(value)
			}
		}
		data[utils.ToString(item.Id)] = utils.ToInt(value)
	}
	userUnitDetail := model.NewPlayerUnitDetail(userUnit, data, statData, unit.Status, unit)
	return userUnitDetail, nil
}

func GetCurrentUnit(context def.Context, userId int) (userUnits []model.UserUnit, err error) {
	query := model.UserUnitModel.Query().Where("=", "user_id", userId).Where(">=", "index", 0).Asc("index")
	if _, err = query.Find(&userUnits); err != nil {
		return nil, SystemExceptionDetail("查找用户部队失败", err)
	}
	return
}

func GetUnitsByIds(context def.Context, userId int, unitsIds []string) (userUnits []model.UserUnit, err error) {
	query := model.UserUnitModel.Query().Where("=", "user_id", userId).Where("in", "id", unitsIds)
	if _, err = query.Find(&userUnits); err != nil {
		return nil, SystemExceptionDetail("查找用户部队失败", err)
	}
	return
}

func UpUnit(context def.Context, user *model.User, userUnit *model.UserUnit, unitInstance *cooperated.Unit, level int) (err error) {
	unit := Center.UnitMap[userUnit.UnitId]
	if userUnit.Level+1 >= len(unit.Levels) {
		return ValidException("部队已是最高级")
	}
	if level <= userUnit.Level {
		return ValidException("部队等级错误")
	}
	levelInfo := unit.Levels[level]
	if !ValidRequire(context, levelInfo.RequireSlice, user, nil, userUnit, unitInstance) {
		return ValidException("不满足升级条件")
	}
	ok, consumeData := ValidConsume(context, levelInfo.ConsumeSlice, 1, user, userUnit)
	if !ok {
		return ValidException("升级所需不足")
	}
	currentLevel := unit.Levels[userUnit.Level]

	if consumeData.UserUnitData == nil {
		consumeData.UserUnitData = map[string]interface{}{}
	}
	consumeData.UserUnitData["level"] = level
	consumeData.UserUnitData["power"] = &orm.UpdateOperate{Operate: "+", Value: levelInfo.PowerPoint - currentLevel.PowerPoint}
	userUnitData := consumeData.UserUnitData

	consumeData.UserUnitData = nil
	if err := UpdateConsume(context, consumeData, user, userUnit); err != nil {
		return err
	}

	if err := UpdateUnit(context, userUnit, userUnitData); err != nil {
		return SystemExceptionDetail("调整部队失败", err)
	}
	return
}

func GoUnit(context def.Context, index int, user *model.User, userUnit *model.UserUnit) (err error) {
	var indexUserUnit model.UserUnit
	if ok, _ := model.UserUnitModel.Query().Where("=", "index", index).Where("=", "user_id", user.Id).One(&userUnit); ok {
		return ValidException("部队无法上场")
	}
	if indexUserUnit.Id == userUnit.Id {
		return ValidException("部队已经上场")
	}

	if err := Env.SingleClean("unit/"+utils.ToString(userUnit.Id), func() error {
		if _, err := model.UserUnitModel.PK(userUnit.Id).Update(map[string]interface{}{
			"index": index,
		}); err != nil {
			return SystemExceptionDetail("派遣部队失败", err)
		}
		return nil
	}, false); err != nil {
		return err
	}

	if indexUserUnit.Id != "" {
		if err := Env.SingleClean("unit/"+utils.ToString(indexUserUnit.Id), func() error {
			if _, err := model.UserUnitModel.PK(userUnit.Id).Update(map[string]interface{}{
				"index": userUnit.Index,
			}); err != nil {
				return SystemExceptionDetail("派遣部队失败", err)
			}
			return nil
		}, false); err != nil {
			return err
		}
	}

	userUnit.Index = index
	return nil
}

func DownUnit(context def.Context, user *model.User, userUnit *model.UserUnit) (err error) {
	if userUnit.Index == -1 {
		return ValidException("部队未上场")
	}
	if err := ChangeUnitIndex(context, -1, user, userUnit); err != nil {
		return err
	}
	return nil
}
